﻿// -------------------------------------------------------------------------
//    @FileName         :    NFMoneyOp.cpp
//    @Author           :    gaoyi
//    @Date             :    2025/1/2
//    @Email            :    445267987@qq.com
//    @Module           :    NFMoneyOp
//
// -------------------------------------------------------------------------

// --- 文件总结 ---------------------------------------------------------------
// 本文件实现 NFMoneyOp 类的功能：
// 
// 【构造/析构】
// - NFMoneyOp：初始化金钱操作器，设置玩家、操作原因等
// - ~NFMoneyOp：析构函数
// 
// 【配置设置】
// - SetCanDecToLessZero：设置允许减少金钱到负数
// 
// 【金钱增加】
// - Inc：增加金钱（两个重载版本：简单版和详细版）
//   * 简单版：返回实际增加数量
//   * 详细版：返回实际增加数量和新的金钱数
// 
// 【金钱减少】
// - Dec：减少金钱（两个重载版本：简单版和详细版）
// - DecAll：减少所有金钱
// 
// 【金钱修改】
// - Modify：修改金钱（可增可减，两个重载版本）
// - SetMoney：设置金钱数量
// 
// 【金钱查询】
// - GetMoney：获取被操作后的金钱数
// 
// 【提交和同步】
// - Commit：提交所有金钱变更
// - PreCheckCommit：预检查提交
// - CommitFill：填充提交日志
// - CommitVirtual：提交虚拟货币
// - CommitReal：提交真实货币
// - SyncToClient：同步到客户端
// - FillPackageInfoForAdd/Del：填充背包通知消息
// 
// 【辅助功能】
// - CheckMoneyType：检查金钱类型
// - MoneyDecNoMoreThanCheck：货币扣除上限检查
// - FindMoney/CreateMoney：查找/创建金钱变更记录
// - IsAddMoneyLimit：检查是否需要检测金钱添加上限
// - Disgorgment：扣除预缴
// ---------------------------------------------------------------------------

#include "NFMoneyOp.h"

#include <NFEventDisp.h>
#include <NFPackageUtil.h>
#include <NFPacketSendUtil.h>
#include <NFPlayer.h>
#include <NFServicePackage.h>

#include "NFlogEventHandler.h"
#include "NFMapPart.h"
#include "proto_event.nanopb.h"
#include "proto_event.pb.h"
#include "proto_log.nanopb.h"
#include "proto_cs_cmd.nanopb.h"
#include "NFComm/NFPluginModule/NFIEventModule.h"


NFMoneyOp::NFMoneyOp(NFPlayer* pPlayer, int iOpReason, bool bNeedCommit):NFBagBaseOp(pPlayer->GetRoleID(), bNeedCommit), m_pPlayer(pPlayer), m_iOpReason(iOpReason), m_bIgnoreLimit(false)
{
    m_bDecToLessZero = false;
    m_iSubReason = 0;
}

NFMoneyOp::~NFMoneyOp()
{

}

void NFMoneyOp::SetCanDecToLessZero()
{
    LOG_DEBUG(m_ownerId, "m_bDecToLessZero:%d", m_bDecToLessZero);
    m_bDecToLessZero = true;
}

int NFMoneyOp::Inc(int enMoneyType, int64_t llMoney, int64_t* pAddedNum)
{
    int iRetCode = 0;
    CHECK_NULL(0, m_pPlayer);
    LOG_DEBUG(m_ownerId, "enMoneyType:{} llMoney:{}", enMoneyType, llMoney);

    int64_t llRealIncMoney = 0;
    int64_t llNewMoney = 0;
    iRetCode = Inc(enMoneyType, llMoney, llRealIncMoney, llNewMoney);
    CHECK_WARN(m_ownerId, iRetCode, "Inc enMoneyType:{} llMoney:{}", enMoneyType, llMoney);

    LOG_DEBUG(m_ownerId, "enMoneyType:{} llRealIncMoney:{} llNewMoney:{}", enMoneyType, llRealIncMoney, llNewMoney);

    if (llRealIncMoney != llMoney)
    {
        // 加钱不一致,不算错误(比如被上限限制了 相加1000 只加了 100)
        LOG_WARN(m_ownerId, -1, "Dec, enMoneyType:{} llMoney:{} llRealIncMoney:{}", enMoneyType, llMoney, llRealIncMoney);

        // 不应该比想加的多
        if (llRealIncMoney > llMoney)
        {
            CHECK_ERR(m_ownerId, -1, "");
        }
    }

    if (pAddedNum)
    {
        *pAddedNum = llRealIncMoney;
    }
    return 0;
}

int NFMoneyOp::Inc(int enMoneyType, int64_t llMoney, int64_t& llRealIncMoney, int64_t& llNewMoney)
{
    int iRetCode = 0;
    CHECK_NULL(0, m_pPlayer);

    LOG_DEBUG(m_ownerId, "enMoneyType:{} llMoney:{}", enMoneyType, llMoney);

    if (llMoney < 0)
    {
        CHECK_WARN(m_ownerId, -1, "invalid llMoney, must >= 0, enMoneyType:{} llMoney:{}", enMoneyType, llMoney);
    }

    iRetCode = Modify(enMoneyType, llMoney, llRealIncMoney, llNewMoney);
    CHECK_ERR(m_ownerId, iRetCode, "Modify enMoneyType:{} llMoney:{}", enMoneyType, llMoney);
    LOG_DEBUG(m_ownerId, "enMoneyType:{} llRealIncMoney:{} llNewMoney:{}", enMoneyType, llRealIncMoney, llNewMoney);

    return 0;
}

int NFMoneyOp::DecAll(int enMoneyType, int64_t* piDelNum)
{
    int64_t llMoney = NFServicePackage::GetMoneyNumber(m_pPlayer, enMoneyType);
    return Dec(enMoneyType, llMoney, piDelNum);
}

int NFMoneyOp::Dec(int enMoneyType, int64_t llMoney, int64_t* piDelNum)
{
    int iRetCode = 0;
    CHECK_NULL(0, m_pPlayer);

    LOG_DEBUG(m_ownerId, "enMoneyType:{} llMoney:{}", enMoneyType, llMoney);

    int64_t llRealDecMoney = 0;
    int64_t llNewMoney = 0;
    iRetCode = Dec(enMoneyType, llMoney, llRealDecMoney, llNewMoney);
    CHECK_WARN(m_ownerId, iRetCode, "Modify enMoneyType:{} llMoney:{}", enMoneyType, llMoney);

    LOG_DEBUG(m_ownerId, "enMoneyType:{} llRealDecMoney:{} llNewMoney:{}", enMoneyType, llRealDecMoney, llNewMoney);

    // 扣的钱和想扣的不一样多，失败(钱不够)
    if (llRealDecMoney != llMoney)
    {
        CHECK_WARN(m_ownerId, ERR_CODE_MONEY_NOT_ENOUGH, "Dec, enMoneyType:{} llMoney:{} llRealDecMoney:{}", enMoneyType, llMoney, llRealDecMoney);
    }

    if (piDelNum)
    {
        *piDelNum = llRealDecMoney;
    }

    return 0;
}

int NFMoneyOp::Dec(int enMoneyType, int64_t llMoney, int64_t& llRealDecMoney, int64_t& llNewMoney)
{
    int iRetCode = 0;
    CHECK_NULL(0, m_pPlayer);

    LOG_DEBUG(m_ownerId, "enMoneyType:{} llMoney:{}", enMoneyType, llMoney);

    if (llMoney < 0)
    {
        CHECK_WARN(m_ownerId, -1, "invalid llMoney, must >= 0, enMoneyType:{} llMoney:{}", enMoneyType, llMoney);
    }

    iRetCode = Modify(enMoneyType, -llMoney, llRealDecMoney, llNewMoney);
    CHECK_WARN(m_ownerId, iRetCode, "Modify enMoneyType:{} llMoney:{}", enMoneyType, llMoney);

    LOG_DEBUG(m_ownerId, "enMoneyType:{} llRealDecMoney:{} llNewMoney:{}", enMoneyType, llRealDecMoney, llNewMoney);

    // 因为实际修改的金钱数是负数 但是外面想要的是正数，保持和传入参数一致
    llRealDecMoney = -llRealDecMoney;

    return 0;
}

int NFMoneyOp::GetMoney(int enMoneyType, int64_t& llMoney)
{
    int iRetCode = 0;
    CHECK_NULL(0, m_pPlayer);

    if (m_bNestCreate) // 是嵌套创建的本对象，不允许操作
    {
        CHECK_ERR(m_ownerId, -1, "nest create, can`t be op");
    }

    iRetCode = CheckMoneyType(enMoneyType);
    CHECK_ERR(m_ownerId, iRetCode, "CheckMoneyType, enMoneyType:{}", enMoneyType);

    int iIndex = INVALID_ID;
    MoneyChange* pMoney = FindMoney(enMoneyType);
    CHECK_ERR(m_ownerId, iRetCode, "FindMoneyIndex, enMoneyType:{}", enMoneyType);
    if (pMoney == nullptr)
    {
        if (m_allMoney.size() >= m_allMoney.max_size()) // 金钱记录满了 ？？？不可能
        {
            CHECK_ERR(0, -1, "m_iMoneyCount:%lu", m_allMoney.size());
        }

        if (!NFItemUtil::IsVirtualMoney(enMoneyType))
        {
            // 获取实际持有金钱
            llMoney = NFServicePackage::GetMoneyNumber(m_pPlayer, enMoneyType);
            LOG_DEBUG(m_ownerId, "enMoneyType:{} iIndex:{} m_iMoneyCount:{} llMoney:{}", enMoneyType, iIndex, m_allMoney.size(), llMoney);

            pMoney = CreateMoney(enMoneyType, llMoney);
            CHECK_NULL(m_ownerId, pMoney);

            llMoney = pMoney->value;
        }
    }
    else
    {
        llMoney = pMoney->value;
    }

    return 0;
}

int NFMoneyOp::Commit(bool bSyncToClient, bool preCheckCommit)
{
    int iRetCode = 0;
    CHECK_NULL(0, m_pPlayer);

    if (!preCheckCommit)
    {
        iRetCode = PreCheckCommit(bSyncToClient);
        CHECK_ERR(m_ownerId, iRetCode, "CommitCheck");

        BaseCommit();
    }

    NFLogPlayerMoneyFlow nflog;
    iRetCode = CommitFill(nflog);
    CHECK_ERR(m_ownerId, iRetCode, "CommitFill");

    iRetCode = CommitVirtual(nflog);
    CHECK_ERR_NT(m_ownerId, iRetCode, "CommitVirtual");

    iRetCode = CommitReal(nflog);
    CHECK_ERR_NT(m_ownerId, iRetCode, "CommitReal");

    m_pPlayer->MarkDirty();

    if (bSyncToClient)
    {
        iRetCode = SyncToClient();
        CHECK_ERR_NT(m_ownerId, iRetCode, "SyncToClient");
    }

    // 进行预缴操作
    iRetCode = Disgorgment();
    CHECK_ERR_NT(m_ownerId, iRetCode, "Disgorgment");

    return 0;
}

int NFMoneyOp::Modify(int enMoneyType, int64_t llMoney)
{
    int iRetCode = 0;
    CHECK_NULL(0, m_pPlayer);

    LOG_DEBUG(m_ownerId, "enMoneyType:{} llMoney:{}", enMoneyType, llMoney);

    int64_t llRealChangeMoney = 0;
    int64_t llNewMoney = 0;
    iRetCode = Modify(enMoneyType, llMoney, llRealChangeMoney, llNewMoney);
    CHECK_WARN(m_ownerId, iRetCode, "Modify enMoneyType:{} llMoney:{}", enMoneyType, llMoney);

    LOG_DEBUG(m_ownerId, "enMoneyType:{} llRealChangeMoney:{} llNewMoney:{}", enMoneyType, llRealChangeMoney, llNewMoney);

    // 钱不够扣算失败
    if (llRealChangeMoney != llMoney && llMoney < 0)
    {
        CHECK_WARN(m_ownerId, ERR_CODE_MONEY_NOT_ENOUGH , "Modify, enMoneyType:{} llMoney:{} llRealChangeMoney:{}", enMoneyType, llMoney, llRealChangeMoney);
    }

    return 0;
}

int NFMoneyOp::Modify(int enMoneyType, int64_t llMoney, int64_t& llRealChangeMoney, int64_t& llNewMoney)
{
    int iRetCode = 0;
    CHECK_NULL(0, m_pPlayer);

    LOG_DEBUG(m_ownerId, "enMoneyType:{} llMoney:{}", enMoneyType, llMoney);

    iRetCode = CheckMoneyType(enMoneyType);
    CHECK_WARN(m_ownerId, iRetCode, "CheckMoneyType, enMoneyType:{}", enMoneyType);

    int64_t llOldMoney = 0;
    iRetCode = GetMoney(enMoneyType, llOldMoney);
    CHECK_ERR(m_ownerId, iRetCode, "GetMoney, enMoneyType:{}", enMoneyType);

    LOG_DEBUG(m_ownerId, "llOldMoney:{}", llOldMoney);
    llRealChangeMoney = llMoney;
    llNewMoney = llOldMoney;
    if (llMoney == 0) // 金钱没有修改
    {
        return 0;
    }

    if (llMoney < 0) // 扣钱
    {
        if (llOldMoney < 0) // 已经是负数了，有可能数值下限溢出
        {
            int64_t const llCanDecMoney = std::numeric_limits<int64_t>::min() - llOldMoney;
            if (llMoney < llCanDecMoney) // 超过数值下限了
            {
                LOG_INFO(m_ownerId, "llOldMoney:{} llCanDecMoney:{}", llOldMoney, llCanDecMoney);

                // 修正 最多减少数
                llRealChangeMoney = llCanDecMoney;
            }
        }
    }
    else // (llMoney > 0) 加钱
    {
        if (llOldMoney > 0) // 已经是正数了，有可能数值上限溢出
        {
            int64_t const llCanIncMoney = std::numeric_limits<int64_t>::max() - llOldMoney;
            // 超过数值上限了
            if (llMoney > llCanIncMoney)
            {
                LOG_INFO(m_ownerId, "llOldMoney:{} llCanIncMoney:{}", llOldMoney, llCanIncMoney);

                // 修正 最多增加数
                llRealChangeMoney = llCanIncMoney;
            }
        }

        if (IsAddMoneyLimit(enMoneyType) == true)
        {
            // 当前可增加货币最大值限制
            int64_t const llMaxCanGainMoney = NFItemUtil::GetCanGainMoneyNum(enMoneyType);
            // 超过配置的上限了
            if (llRealChangeMoney > llMaxCanGainMoney)
            {
                LOG_DEBUG(m_ownerId, "llMaxCanGainMoney:{} llRealChangeMoney:{}", llMaxCanGainMoney, llRealChangeMoney);

                // 修正 最多增加数
                llRealChangeMoney = llMaxCanGainMoney;
            }
        }
    }

    llNewMoney = llOldMoney + llRealChangeMoney;
    LOG_DEBUG(m_ownerId, "llOldMoney:{} llRealChangeMoney:{} llNewMoney:{}", llOldMoney, llRealChangeMoney, llNewMoney);

    if (llMoney < 0) // 扣钱操作
    {
        if (llNewMoney < 0) // 扣成负数了
        {
            if (!m_bDecToLessZero) // 不能扣成负数 钱不够
            {
                CHECK_WARN(m_ownerId, ERR_CODE_MONEY_NOT_ENOUGH, "can`t dec less zero");
            }
        }
        iRetCode = MoneyDecNoMoreThanCheck(enMoneyType, llNewMoney);
        CHECK_WARN(m_ownerId, iRetCode, "Money Dec No More Than Check Failed Type:%d %ld %ld %ld %ld",
                   enMoneyType, llMoney, llOldMoney, llRealChangeMoney, llNewMoney);
    }

    iRetCode = SetMoney(enMoneyType, llNewMoney);
    CHECK_ERR(m_ownerId, iRetCode, "SetMoney");

    NFEventDisp::OnItemChange(m_ownerId, enMoneyType, 0, 0, llMoney, llNewMoney, m_iOpReason, m_llLogParam);

    return 0;
}

int NFMoneyOp::CheckMoneyType(int enMoneyType)
{
    CHECK_NULL(0, m_pPlayer);

    CHECK_EXPR(NFItemUtil::IsValidMoney(enMoneyType), -1, "enMoneyType:{} is not valid", enMoneyType);

    return 0;
}

int NFMoneyOp::SetMoney(int enMoneyType, int64_t llMoney)
{
    int iRetCode = 0;
    CHECK_NULL(0, m_pPlayer);
    LOG_DEBUG(m_ownerId, "enMoneyType:{} llMoney:{}", enMoneyType, llMoney);

    if (m_bNestCreate) // 是嵌套创建的本对象，不允许操作
    {
        CHECK_ERR(m_ownerId, -1, "nest create, can`t be op");
    }

    iRetCode = CheckMoneyType(enMoneyType);
    CHECK_ERR(m_ownerId, iRetCode, "CheckMoneyType, enMoneyType:%d", enMoneyType);

    MoneyChange* pMoney = FindMoney(enMoneyType);
    if (pMoney == nullptr)
    {
        pMoney = CreateMoney(enMoneyType, 0);
        CHECK_NULL(m_ownerId, pMoney);
    }

    pMoney->value = llMoney;
    return 0;
}

int NFMoneyOp::SyncToClient()
{
    CHECK_NULL(0, m_pPlayer);

    // 没有金钱变化
    if (m_allMoney.size() <= 0)
    {
        return 0;
    }

    if (!m_bCommit)
    {
        CHECK_ERR(m_ownerId, -1, "not commit");
    }

    proto_ff::Proto_CSRsp respond;
    proto_ff::Proto_CSRoleItemNtf* pNtf = respond.mutable_role_item_ntf();
    auto pNtfList = pNtf->mutable_item_list();
    for (int i = 0; i < (int)m_allMoney.size(); i++)
    {
        MoneyChange& money= m_allMoney[i];
        auto pNtfData = pNtfList->Add();
        pNtfData->set_id(money.id);
        pNtfData->set_quality(0);
        pNtfData->set_value(money.value);
    }

    NFPacketSendUtil::SendToClient(m_pPlayer, proto_ff::E_CS_ROLE_ITEM_NTF, &respond);

    return 0;
}

int NFMoneyOp::MoneyDecNoMoreThanCheck(int enMoneyType, int64_t llNewMoney)
{
    return 0;
}

MoneyChange* NFMoneyOp::FindMoney(int enMoneyType)
{
    for (int i = 0;i < (int)m_allMoney.size(); i++)
    {
        if ((int)m_allMoney[i].id == enMoneyType)
        {
            return &m_allMoney[i];
        }
    }

    return nullptr;
}

MoneyChange* NFMoneyOp::CreateMoney(int enMoneyType, int64_t iMoneyNum)
{
    CHECK_EXPR(m_allMoney.size() < m_allMoney.max_size(), nullptr, "allMoney size:{} >= max_size:{} moneyType:{}, iMoneyNum:{}", m_allMoney.size(), m_allMoney.max_size(), enMoneyType, iMoneyNum);
    MoneyChange mon;
    mon.id = enMoneyType;
    mon.value = iMoneyNum;
    mon.value = 0;
    m_allMoney.push_back(mon);
    return &m_allMoney.back();
}

bool NFMoneyOp::IsAddMoneyLimit(int enMoneyType)
{
    if (m_bIgnoreLimit == true)
    {
        // 设置忽略上限，则不限制
        return false;
    }

    auto pDesc = ItemDesc::Instance()->GetDesc(enMoneyType);
    if (pDesc && pDesc->item_max_hold > 0)
    {
        return true;
    }

    // 默认限制上限
    return false;
}

int NFMoneyOp::PreCheckCommit(bool bSyncToClient)
{
    LOG_TRACE(m_ownerId, "m_allMoney.size():%lu bSyncToClient:%d", m_allMoney.size(), bSyncToClient);

    return BaseCommitCheck();
}

int NFMoneyOp::CommitFill(NFLogPlayerMoneyFlow& nflog)
{
    auto pMapPart = m_pPlayer->GetPart<NFMapPart>();
    CHECK_NULL(0, pMapPart);
    nflog.iSequence   = 0;
    nflog.iReason     = m_iOpReason;
    nflog.iSubReason = m_iSubReason;
    nflog.llParam1 = m_llLogParam;
    nflog.iMapInstID   = pMapPart->GetMapInstId();
    nflog.iMapDescID   = pMapPart->GetMapData()->map_desc_id;
    nflog.iPosX    = pMapPart->GetMapData()->pos.x;
    nflog.iPosY    = pMapPart->GetMapData()->pos.y;
    nflog.iPosZ    = pMapPart->GetMapData()->pos.z;
    return 0;
}

int NFMoneyOp::CommitVirtual(NFLogPlayerMoneyFlow& nflog)
{
    int iRetCode = 0;
    for (int i = 0; i < (int)m_allMoney.size(); i++)
    {
        MoneyChange& money = m_allMoney[i];
        // 处理虚拟货币
        if (!NFItemUtil::IsVirtualMoney(money.id))
        {
            continue;
        }

        int64_t llIncMoney = money.value;
        if (llIncMoney == 0)
        {
            continue;
        }

        LOG_DEBUG(m_ownerId, "i:{} enMoneyType:{} reason:{} llIncMoney:{}", i, m_iOpReason, money.id, llIncMoney);

        if (llIncMoney < 0)
        {
            LOG_ERR(m_ownerId, -1, "can't dec, i:{} enMoneyType:{} reason:{} llIncMoney:{}", i, m_iOpReason, money.id, llIncMoney);
            continue;
        }

        iRetCode = NFServicePackage::OnVirtualMoneyInc(m_pPlayer, money.id, llIncMoney, m_iOpReason, m_iSubReason);
        if (iRetCode)
        {
            LOG_ERR(m_ownerId, iRetCode, "OnVirtualMoneyInc Failed, i:{} enMoneyType:{} reason:{} llIncMoney:{}", i, m_iOpReason, money.id, llIncMoney)
            continue;
        }

        proto_ff::EventPlayerMoneyInc stEventParam;
        stEventParam.set_reason(m_iOpReason);
        stEventParam.set_sub_reason(m_iSubReason);
        stEventParam.set_money_type(money.id);
        stEventParam.set_value(llIncMoney);
        FindModule<NFIEventModule>()->FireExecute(NF_ST_LOGIC_SERVER, EVENT_PLAYER_MONEY_INC, EVENT_SRC_TYPE_PLAYER, m_ownerId, stEventParam);
    }
    return 0;
}

int NFMoneyOp::CommitReal(NFLogPlayerMoneyFlow& nflog)
{
    int iRetCode = 0;
    for (int i = 0; i < (int)m_allMoney.size(); i++)
    {
        MoneyChange& money = m_allMoney[i];
        // 不处理虚拟货币
        if (NFItemUtil::IsVirtualMoney(money.id))
        {
            continue;
        }

        int64_t llNewMoney = money.value;
        int64_t llOldMoney = NFServicePackage::GetMoneyNumber(m_pPlayer, money.id);
        if (llNewMoney == llOldMoney)
        {
            continue;
        }

        LOG_DEBUG(m_ownerId, "i:{} enMoneyType:{} llOldMoney:{} llNewMoney:{}", i, money.id, llOldMoney, llNewMoney);

        iRetCode = NFServicePackage::SetMoneyNumber(m_pPlayer, money.id, llNewMoney);
        CHECK_ERR_NT(m_ownerId, iRetCode, "SetMoneyNumber, i:{} enMoneyType:{} llOldMoney:{} llNewMoney:{}", i, money.id, llOldMoney, llNewMoney);

        // 记录货币变动
        money.change = llNewMoney - llOldMoney;

        nflog.iMoneyType     = money.id;
        nflog.llAfterMoney   = llNewMoney;
        nflog.llMoney        = money.change;

        // 货币变动值(这里不用int64 因为gm操作时变动值可能超过数值上限)
        uint64_t ullChangeValue = 0;
        if (llOldMoney < llNewMoney) // 增加金钱
        {
            // 从负数增加到正数，增加的货币数可能会超过int64上限
            if (llOldMoney < 0 && llNewMoney > 0)
            {
                // 从负值增加到0
                ullChangeValue = -llOldMoney;
                // 从0增加到新货币值
                ullChangeValue += llNewMoney;

                // 一次操作增加的金钱超过了货币上限(不应该出现 除非gm)
                if (ullChangeValue > (uint64_t)std::numeric_limits<int64_t>::max())
                {
                    // 调整为极大值
                    nflog.llMoney = std::numeric_limits<int64_t>::max();
                    // 调整为极大值
                    LOG_ERR(m_ownerId, -1, "i:{} enMoneyType:{} llOldMoney:{} llNewMoney:{} ullChangeValue:{}", i, money.id, llOldMoney, llNewMoney, ullChangeValue);
                }
            }
            else // 增加前后，数值符号未发生变化, 增加的值必然不会超过int64上限
            {
                ullChangeValue = llNewMoney - llOldMoney;
            }

            proto_ff::EventPlayerMoneyInc stEventParam;
            stEventParam.set_reason(m_iOpReason);
            stEventParam.set_sub_reason(m_iSubReason);
            stEventParam.set_money_type(money.id);
            stEventParam.set_value(ullChangeValue);
            FindModule<NFIEventModule>()->FireExecute(NF_ST_LOGIC_SERVER, EVENT_PLAYER_MONEY_INC, EVENT_SRC_TYPE_PLAYER, m_ownerId, stEventParam);
        }
        else // (llOldMoney > llNewMoney) 减少金钱
        {
            // 从正数减少到负数，减少的货币数可能会超过int64上限
            if (llOldMoney > 0 && llNewMoney < 0)
            {
                // 从正数减少到0
                ullChangeValue = llOldMoney;
                // 从0减少的新货币值
                ullChangeValue += -llNewMoney;

                // 一次操作减少的金钱超过了货币上限(不应该出现  除非gm)
                if (ullChangeValue > (uint64_t)std::numeric_limits<int64_t>::max())
                {
                    // 调整为极小值
                    nflog.llMoney = std::numeric_limits<int64_t>::min();
                    LOG_ERR(m_ownerId, -1, "i:{} enMoneyType:{} llOldMoney:{} llNewMoney:{} ullChangeValue:{}", i, money.id, llOldMoney, llNewMoney, ullChangeValue);
                }
            }
            else // 减少前后，数值符号未发生变化, 减少的值必然不会超过int64上限
            {
                ullChangeValue = llOldMoney - llNewMoney;
            }

            proto_ff::EventPlayerMoneyDec stEventParam;
            stEventParam.set_reason(m_iOpReason);
            stEventParam.set_sub_reason(m_iSubReason);
            stEventParam.set_money_type(money.id);
            stEventParam.set_value(ullChangeValue);
            FindModule<NFIEventModule>()->FireExecute(NF_ST_LOGIC_SERVER, EVENT_PLAYER_MONEY_DEC, EVENT_SRC_TYPE_PLAYER, m_ownerId, stEventParam);
        }

        NFlogEventHandler::OnMoneyFlow(m_pPlayer, nflog);
    }
    return 0;
}

int NFMoneyOp::FillPackageInfoForAdd(proto_ff::Proto_CSRoleItemNtf* pNtf)
{
    if (!m_bCommit) return 0;
    auto pNtfList = pNtf->mutable_item_list();
    for (int i = 0; i < (int)m_allMoney.size(); i++)
    {
        MoneyChange& money = m_allMoney[i];
        if (money.change > 0)
        {
            auto pNtfData = pNtfList->Add();
            pNtfData->set_id(money.id);
            pNtfData->set_quality(0);
            pNtfData->set_value(money.change);
        }
    }
    return 0;
}

int NFMoneyOp::FillPackageInfoForDel(proto_ff::Proto_CSRoleItemNtf* pNtf)
{
    if (!m_bCommit) return 0;
    auto pNtfList = pNtf->mutable_item_list();
    for (int i = 0; i < (int)m_allMoney.size(); i++)
    {
        MoneyChange& money = m_allMoney[i];
        if (money.change < 0)
        {
            auto pNtfData = pNtfList->Add();
            pNtfData->set_id(money.id);
            pNtfData->set_quality(0);
            pNtfData->set_value(-money.change);
        }
    }
    return 0;
}

int NFMoneyOp::Disgorgment()
{
    return 0;
}
